﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using doubanloginDll8;
using MimiDouban.Abstract;
using MimiDouban.Abstract.Exceptions;
using MimiDouban.Abstract.Beans;
using System.Threading;
using System.Windows.Threading;
using MimiDouban.Test;
using MimiDouban.Extention;
using System.Diagnostics;

namespace MimiDouban.Control
{
    /// <summary>
    /// 控制器的实现类
    /// </summary>
    public class Controller : IController
    {
        /// <summary>
        /// UI的引用
        /// </summary>
        private IMainUI ui = null;

        /// <summary>
        /// 音乐提供器的引用
        /// </summary>
        private ISongProvider songProvider = null;

        /// <summary>
        /// 播放器的引用
        /// </summary>
        private IPlayer player = null;

        /// <summary>
        /// 主线程调度器
        /// </summary>
        private Dispatcher mainDispatcher;

        /// <summary>
        /// 程序当前状态
        /// </summary>
        private ProgramStatus currentStatus;

        private DoubanChannel currentChannel = null;

        private int failCount = 0;//失败次数，如果失败次数超过5次的话，就直接跳到下一首
        private bool willChangeToPrivateChannel = false;

        #region IController Members

        public void setMainUI(IMainUI mainUI)
        {
            this.ui = mainUI;
        }

        public void setSongProvider(ISongProvider provider)
        {
            this.songProvider = provider;
        }

        public void setPlayer(IPlayer player)
        {
            this.player = player;
        }

        public void start()
        {
            if (this.ui == null || this.songProvider == null || this.player == null)
            {
                throw new NotInitializedException();
            }

            mainDispatcher = Dispatcher.CurrentDispatcher;

            //绑定UI的事件
            this.ui.UIStarted += new UIHandler(ui_UIStarted);
            this.ui.VolumeChanged += new VolumeChangedHandler(ui_VolumeChanged);
            this.ui.PauseClicked += new ButtonClickHandler(ui_PauseClicked);
            this.ui.NextClicked += new ButtonClickHandler(ui_NextClicked);
            this.ui.LikeClicked += new ButtonClickHandler(ui_LikeClicked);
            this.ui.DisikeClicked += new ButtonClickHandler(ui_DisikeClicked);
            this.ui.ChannelChoosen += new ChannelChooseHandler(ui_ChannelChoosen);
            this.ui.UserLogin += new UserLoginHandler(ui_UserLogin);
            this.ui.CloseClicked += new ButtonClickHandler(ui_CloseClicked);

            //绑定Player的事件
            this.player.PlayFinished += new PlayerEventHandler(player_PlayFinished);
            this.player.PlayFailed += new PlayerFailedEventHandler(player_PlayFailed);
            this.player.BufferingEnd += new PlayerEventHandler(player_BufferingEnd);
            this.player.BufferingBegin += new PlayerEventHandler(player_BufferingBegin);
            this.player.PlayerTicked += new PlayerTickEventHandler(player_PlayerTicked);

            this.initUserSetting();

            //UI启动
            this.ui.start();
            this.currentStatus = ProgramStatus.Starting;

        }
        private void initUserSetting()
        {
            //用户设置
            double volume = DataStore.getInstance().getDouble("volume");
            if (!volume.Equals(double.NaN))
            {
                this.player.setVolume(volume);
                this.ui.showVolume(volume);
            }
        }
        #endregion

        #region UI Event Handlers


        public delegate void ShouInitInfoDelType(DoubanSong _firstSong, DoubanChannel _firstChannel, string _firstUsername);
        /// <summary>
        /// UI启动动画完成时触发该方法
        /// </summary>
        private void ui_UIStarted()
        {
            //使用新线程去执行后台操作
            new Thread(new ThreadStart(delegate()
            {
                //获取第一首歌和初始频道
                DoubanSong firstSong = null;
                DoubanChannel firstChannel = null;
                int firstChannelId;
                string firstUsername = "";

                try
                {
                    songProvider.onInit(out firstSong, out firstChannelId, out firstUsername);
                    firstChannel = findChannelById(firstChannelId);                    
                }
                catch (Exception e)
                {
                    MimiDouban.Test.TestLog.getInstance().error("网络连接失败，UI启动动画完成时触发该方法，ui_UIStarted", e);
                    BugReport.ShowReport("网络连接失败", e);
                    this.mainDispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate()
                    {
                        this.ui_CloseClicked();
                    });
                    return;
                }

                //再使用UI线程来显示结果
                this.mainDispatcher.BeginInvoke(DispatcherPriority.Normal, (ShouInitInfoDelType)delegate(DoubanSong _firstSong, DoubanChannel _firstChannel, string _firstUsername)
                {
                    //在界面上显示第一首歌的信息
                    this.ui.ShowNextSong(_firstSong);
                    //显示频道
                    ui.ShowChannel(_firstChannel);
                    //显示用户名
                    if (_firstUsername != null)
                    {
                        this.ui.showCurrentUser(_firstUsername);
                    }
                    else//否则显示登录按钮
                    {
                        this.ui.showLoginBtn();
                    }

                    this.currentChannel = _firstChannel;

                    //播放器播放第一首歌
                    this.player.play(_firstSong.Url);
                    this.currentStatus = ProgramStatus.Normal;
                }, firstSong, firstChannel,firstUsername);
            })).Start();
        }

        /// <summary>
        /// 设置音量时触发改方法
        /// </summary>
        /// <param name="newVolume"></param>
        private void ui_VolumeChanged(double newVolume)
        {
            if (this.currentStatus == ProgramStatus.Starting
                || this.currentStatus == ProgramStatus.Closing)
            {
                return;
            }
            this.player.setVolume(newVolume);//在Player上设置新的音量
        }

        /// <summary>
        /// 暂停按钮按下时触发该方法
        /// </summary>
        private void ui_PauseClicked()
        {
            if (this.currentStatus == ProgramStatus.Starting
                || this.currentStatus == ProgramStatus.Closing)
            {
                return;
            }
            if (this.player.isPaused())//如果已经暂停了
            {
                this.player.resume();//恢复播放
                this.ui.setPauseStatus(false);//暂停按钮变为原来状态
            }
            else//如果没有处理暂停状态
            {
                this.player.pause();//暂停
                this.ui.setPauseStatus(true);//按钮处于已暂停状态
            }
        }




        public delegate void ShouSongInfoDelType(DoubanSong _song);
        /// <summary>
        /// 下一首按钮按下时触发该方法
        /// </summary>
        private void ui_NextClicked()
        {
            if (this.currentStatus == ProgramStatus.Starting
                || this.currentStatus == ProgramStatus.Closing)
            {
                return;
            }
            this.currentStatus = ProgramStatus.NextRequested;
            this.player.pause();
            //使用新线程去执行后台操作
            new Thread(new ThreadStart(delegate()
            {
                DoubanSong nextSong;
                try
                {
                    nextSong = this.songProvider.onNext();//从songprovider获取下一首歌
                    if (nextSong == null)
                        throw new Exception("The returned nextSong is null");
                }
                catch (Exception e)
                {
                    MimiDouban.Test.TestLog.getInstance().error("获取下一首歌曲失败，下一首按钮按下时触发该方法，ui_NextClicked", e);
                    BugReport.ShowReport("获取下一首歌曲失败", e);
                    this.mainDispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate()
                    {
                        this.ui_CloseClicked();
                    });
                    return;
                }

                //再使用UI线程来显示结果
                this.mainDispatcher.BeginInvoke(DispatcherPriority.Normal, (ShouSongInfoDelType)delegate(DoubanSong _song)
                {
                    this.player.play(nextSong.Url);//用Player来播放下一首歌
                    this.ui.ShowNextSong(_song);//在界面上显示下一首歌
                    this.currentStatus = ProgramStatus.Normal;
                }, nextSong);
            })).Start();
        }


        public delegate void ShowLikeResDelType(bool res);
        /// <summary>
        /// 喜欢按钮按下时触发该方法
        /// </summary>
        private void ui_LikeClicked()
        {
            if (this.currentStatus == ProgramStatus.Starting
                || this.currentStatus == ProgramStatus.Closing)
            {
                return;
            }

            this.currentStatus = ProgramStatus.LikeRequested;

            if (this.ui.getLikeStatus() == ControlStatus.Enabled)//如果本来是未喜欢状态
            {
                this.ui.setLikeStatus(ControlStatus.Pressed);//设置按钮状态

                //使用新线程去执行后台操作
                new Thread(new ThreadStart(delegate()
                {
                    DoubanSong nextSong;
                    bool res = false;
                    try
                    {
                        res = this.songProvider.onLike();//使用songProvider发出喜欢报告
                    }
                    catch (Exception e)
                    {
                        MimiDouban.Test.TestLog.getInstance().error("喜欢歌曲失败", e);
                        res = false;
                    }
                    this.mainDispatcher.BeginInvoke(DispatcherPriority.Normal, (ShowLikeResDelType)delegate(bool _res)
                    {
                        if (_res == false)
                        {
                            this.ui.setLikeStatus(ControlStatus.Enabled);
                        }
                        this.currentStatus = ProgramStatus.Normal;
                    }, res);
                })).Start();
            }
            else
            {
                this.ui.setLikeStatus(ControlStatus.Enabled);//设置按钮状态

                //使用新线程去执行后台操作
                new Thread(new ThreadStart(delegate()
                {
                    bool res = this.songProvider.onLikeCancelled();//用SongProvider发送取消喜欢报告
                    this.mainDispatcher.BeginInvoke(DispatcherPriority.Normal, (ShowLikeResDelType)delegate(bool _res)
                    {
                        if (_res == false)
                        {
                            this.ui.setLikeStatus(ControlStatus.Pressed);
                        }
                        this.currentStatus = ProgramStatus.Normal;
                    }, res);
                })).Start();
            }

        }

        /// <summary>
        /// 不喜欢按钮按下时触发该方法
        /// </summary>
        private void ui_DisikeClicked()
        {
            if (this.currentStatus == ProgramStatus.Starting
                || this.currentStatus == ProgramStatus.Closing
                || this.currentStatus == ProgramStatus.NextRequested
                || this.currentChannel.ChannelId != "0")
            {
                return;
            }

            this.currentStatus = ProgramStatus.NextRequested;
            this.player.pause();
            //使用新线程去执行后台操作
            new Thread(new ThreadStart(delegate()
            {
                DoubanSong nextSong;

                try
                {
                    nextSong = this.songProvider.onDislike();//报告不喜欢，并获取下一首歌
                    if (nextSong == null)
                        throw new Exception("The returned nextSong is null");
                }
                catch (Exception e)
                {
                    MimiDouban.Test.TestLog.getInstance().error("报告不喜欢失败", e);
                    BugReport.ShowReport("报告不喜欢失败", e);
                    this.mainDispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate()
                    {
                        this.ui_CloseClicked();
                    });
                    return;
                }

                //再使用UI线程来显示结果
                this.mainDispatcher.BeginInvoke(DispatcherPriority.Normal, (ShouSongInfoDelType)delegate(DoubanSong _song)
                {
                    this.player.play(_song.Url);//播放下一首歌
                    this.ui.ShowNextSong(_song);//显示下一首歌
                    this.currentStatus = ProgramStatus.Normal;
                }, nextSong);
            })).Start();
        }


        public delegate void ShouChannelInfoDelType(DoubanSong _song, int _channelId);

        /// <summary>
        /// 频道切换时触发该方法
        /// </summary>
        /// <param name="channelId">新频道ID</param>
        private void ui_ChannelChoosen(int channelId)
        {
            if (this.currentStatus == ProgramStatus.Starting
                || this.currentStatus == ProgramStatus.Closing
                || this.currentStatus == ProgramStatus.NextRequested)
            {
                return;
            }
            if (channelId == 0 && !this.songProvider.isLogin())//如果是私人频道，且未登录
            {
                willChangeToPrivateChannel = true;
                this.ui.showLogin();//显示登录界面
                return;
            }

            this.currentStatus = ProgramStatus.NextRequested;
            this.player.pause();
            //使用新线程去执行后台操作
            new Thread(new ThreadStart(delegate()
            {
                DoubanSong nextSong;

                try
                {
                    nextSong = this.songProvider.onChannelChanged(channelId);//使用songProvider报告切换频道
                    if (nextSong == null)
                        throw new Exception("The returned nextSong is null");
                }
                catch (Exception e)
                {
                    MimiDouban.Test.TestLog.getInstance().error("切换频道失败", e);
                    BugReport.ShowReport("切换频道失败", e);
                    this.mainDispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate()
                    {
                        this.ui_CloseClicked();
                    });
                    return;
                }

                //再使用UI线程来显示结果
                this.mainDispatcher.BeginInvoke(DispatcherPriority.Normal, (ShouChannelInfoDelType)delegate(DoubanSong _song, int _channelId)
                {
                    this.player.play(_song.Url);//播放新歌
                    this.ui.ShowNextSong(_song);//显示新歌
                    DoubanChannel nextChannel = findChannelById(_channelId);
                    this.ui.ShowChannel(nextChannel);//显示新频道
                    this.currentStatus = ProgramStatus.Normal;
                    this.currentChannel = nextChannel;
                }, nextSong, channelId);
            })).Start();
        }

        /// <summary>
        /// 用户登陆时触发该方法
        /// </summary>
        /// <param name="email">用户名</param>
        /// <param name="password">密码</param>
        /// <returns>成功状态</returns>
        private DoubanUser ui_UserLogin(string email, string password)//用户登录
        {
            if (this.currentStatus == ProgramStatus.Starting
                || this.currentStatus == ProgramStatus.Closing || this.currentStatus == ProgramStatus.LoginRequested)
            {
                return null;
            }
            DoubanUser result;
            try
            {
                result = this.songProvider.login(email, password);//登录
            }
            catch (Exception e)
            {
                MimiDouban.Test.TestLog.getInstance().error("登录异常", e);
                BugReport.ShowReport("登录异常", e);
                result = null;
            }

            if (result == null)
            {
                return null;
            }

            if (willChangeToPrivateChannel)
            {
                DoubanSong nextSong = this.songProvider.onChannelChanged(0);
                this.player.play(nextSong.Url);
                this.ui.ShowSongInfo(nextSong);
                DoubanChannel nextChannel = findChannelById(0);
                this.ui.ShowChannel(nextChannel);
                willChangeToPrivateChannel = false;
            }
            return result;
        }

        //关闭时
        private void ui_CloseClicked()
        {
            if (this.currentStatus == ProgramStatus.Closing)
            {
                return;
            }

            saveUserSetting();

            this.player.distroy();
            ((IInputUI)this.ui).end();
            this.songProvider.end();

            DataStore.getInstance().end();
        }

        private void saveUserSetting()
        {
            DataStore.getInstance().saveString("volume", this.player.getVolume().ToString());
        }

        #endregion

        #region Player Event Handlers

        /// <summary>
        /// 一首歌播放完成时触发该方法
        /// </summary>
        private void player_PlayFinished()
        {
            this.currentStatus = ProgramStatus.NextRequested;
            this.player.stop();
            //使用新线程去执行后台操作
            new Thread(new ThreadStart(delegate()
            {
                DoubanSong nextSong;
                try
                {
                    nextSong = this.songProvider.onFinished();//获取下一首个
                    if (nextSong == null)
                        throw new Exception("The returned nextSong is null");
                    else
                    {
                        MimiDouban.Test.TestLog.getInstance().info("contrller player_PlayFinished song title:" + nextSong.Title);
                    }
                }
                catch (Exception e)
                {
                    MimiDouban.Test.TestLog.getInstance().error("获取下一首歌失败，一首歌播放完成时触发该方法，player_PlayFinished", e);
                    BugReport.ShowReport("获取下一首歌失败", e);
                    this.mainDispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate()
                    {
                        this.ui_CloseClicked();
                    });
                    return;
                }
                //再使用UI线程来显示结果
                if ( this.mainDispatcher  == null )
                {
                    MimiDouban.Test.TestLog.getInstance().error("contrller player_PlayFinished mainDispatcher  == null");
                }
                this.mainDispatcher.Invoke(DispatcherPriority.Normal, (ShouSongInfoDelType)delegate(DoubanSong _song)
                {
                    try
                    {
                        MimiDouban.Test.TestLog.getInstance().info("controller player_finished before play show result:" + _song.Title);
                        this.player.play(_song.Url);//播放下一首歌
                        MimiDouban.Test.TestLog.getInstance().info("controller player_finished after play show result:" + _song.Title);
                        this.ui.ShowNextSong(_song);//显示下一首歌
                        this.currentStatus = ProgramStatus.Normal;
                    }
                    catch (System.Exception ex)
                    {
                        MimiDouban.Test.TestLog.getInstance().error("controller player_finished beginInvoke:" + ex);

                    }
                }, nextSong);
            })).Start();
        }

        private void player_PlayFailed(Exception e)
        {
            failCount++;
            MimiDouban.Test.TestLog.getInstance().error("播放异常，controller player_PlayFailed，失败次数:"+failCount, e);
            if (failCount < 10)//失败次数小于五次，播放下一首，否则程序异常停止。
            {
                this.player_PlayFinished();
            }
            else
            {

                BugReport.ShowReport("网络出现异常", e);
                this.mainDispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate()
                {
                    this.ui_CloseClicked();
                });
            }
        }

        /// <summary>
        /// 缓冲结束
        /// </summary>
        private void player_BufferingEnd()
        {
            Debug.WriteLine("controller player_BufferingEnd!");
            failCount = 0;//缓冲结束了肯定是开始播放了
            this.ui.showBuffer("");
        }

        /// <summary>
        /// 缓存开始
        /// </summary>
        private void player_BufferingBegin()
        {
            this.ui.showBuffer("正在缓冲...");
            //throw new NotImplementedException();
        }

        /// <summary>
        /// 时间跳动，要显示到界面上
        /// </summary>
        /// <param name="current"></param>
        private void player_PlayerTicked(int current)
        {
            int second = current % 60;
            int mininute = current / 60 % 60;
            this.ui.showTime(mininute, second);
        }

        #endregion

        #region Private Functional Method
        private DoubanChannel findChannelById(int channelId)
        {
            for (int i = 0; i < this.ui.Channels.Length; i++)
            {
                if (channelId.ToString().Equals(this.ui.Channels[i].ChannelId))
                {
                    return this.ui.Channels[i];
                }
            }
            return null;
        }
        #endregion

    }
}
